"""
TCP/IP通信控制器 - 用于通过TCP/IP协议进行连接与数据收发
"""
import os
import socket
import time
import json
import threading

class TCPIPCommunicator:
    """
    TCP/IP通信控制器类，专注于TCP/IP连接与数据收发功能
    支持建立TCP服务端、客户端连接以及数据传输
    """
    def __init__(self, device_ip=None, port=8990, receive_timeout=10):
        """
        初始化函数

        参数:
            device_ip (str): 目标设备的IP地址，如果为None则作为服务器模式
            port (int): 通信端口号，默认为8990
            receive_timeout (int): 接收超时时间（秒），默认为10
        """
        self.device_ip = device_ip
        self.port = port
        self.connected = False
        self.socket = None
        self.server_socket = None
        self.received_data = []
        self.server_thread = None
        self.running = False
        self.receive_timeout = receive_timeout  # 设置接收超时时间
        self.connection_time = None  # 记录连接建立时间
        self.mac = ""

        # 如果提供了IP地址，则作为客户端连接；否则作为服务器监听
        if device_ip:
            self.connect_as_client()
        else:
            self.start_server()

    def connect_as_client(self):
        """
        以客户端模式连接到目标设备

        返回:
            bool: 如果连接成功则返回True
        """
        try:
            print(f"正在尝试连接到设备 {self.device_ip}:{self.port}...")
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 设置套接字超时
            self.socket.settimeout(self.receive_timeout)
            self.socket.connect((self.device_ip, self.port))
            self.connected = True
            self.connection_time = time.time()
            print(f"成功连接到设备 {self.device_ip}:{self.port}!")
            # 启动接收线程
            self.running = True
            self.receive_thread = threading.Thread(target=self._receive_data, daemon=True)
            self.receive_thread.start()
            print("接收线程已启动")
            return True
        except socket.timeout:
            self.connected = False
            print(f"连接设备 {self.device_ip}:{self.port} 超时")
            return False
        except Exception as e:
            self.connected = False
            print(f"无法连接到设备 {self.device_ip}:{self.port}: {str(e)}")
            return False

    def _receive_data(self):
        """
        接收数据的内部方法，处理并解析接收到的数据
        """
        print("进入接收数据循环...")
        while self.running and self.connected and self.socket:
            try:
                # 设置单次接收超时
                self.socket.settimeout(self.receive_timeout)
                data = self.socket.recv(4096)  # 增加缓冲区大小以处理较大的数据包
                if not data:
                    print("连接已关闭 (对方主动关闭)")
                    self.connected = False
                    break

                # 解码接收到的数据
                received_str = data.decode('utf-8', errors='replace')  # 使用replace策略处理编码错误
                print(f"[TCP/IP_read]: {received_str}")

                # 解析JSON数据
                try:
                    received_json = json.loads(received_str)
                    # 存储解析后的JSON对象而不是原始字符串
                    self.received_data.append(received_json)

                    # 检查响应类型并处理
                    if "Init_RESPONSE" in received_json:
                        init_response = received_json["Init_RESPONSE"]
                        if "Content" in init_response and init_response["Content"] == "OK":
                            print("初始化响应: 成功")
                        else:
                            print(f"初始化响应: {init_response}")

                    elif "BLE_SCAN" in received_json:
                        scan_data = received_json["BLE_SCAN"]
                        print(f"收到BLE扫描响应: {scan_data}")  # 增加调试信息
                        # 解析扫描数据（可能是字符串形式的JSON）
                        try:
                            scan_json = json.loads(scan_data)
                            print(f"BLE扫描结果: 名称={scan_json.get('name')}, MAC={scan_json.get('mac')}, RSSI={scan_json.get('rssi')}")
                            self.mac = scan_json.get('mac')
                        except json.JSONDecodeError:
                            print(f"BLE扫描原始数据: {scan_data}")

                    elif "CMD_RESPONSE" in received_json:
                        cmd_response = received_json["CMD_RESPONSE"]
                        if "stopLeScan" in cmd_response and cmd_response["stopLeScan"] == "OK":
                            print("停止扫描响应: 成功")
                        else:
                            print(f"命令响应: {cmd_response}")
                             
                    elif "BLE_STATE" in received_json:
                        state_data = received_json["BLE_STATE"]
                        print(f"收到BLE状态响应: {state_data}")
                        # 解析状态数据（可能是字符串形式的JSON）
                        try:
                            state_json = json.loads(state_data)
                            print(f"BLE状态: {state_json.get('MESSAGE')}")
                        except json.JSONDecodeError:
                            print(f"BLE状态原始数据: {state_data}")
                             
                    elif "BLE_READ" in received_json:
                        read_data = received_json["BLE_READ"]
                        print(f"收到BLE读取数据: {read_data}")

                    else:
                        print(f"未知响应类型: {received_json}")

                except json.JSONDecodeError as je:
                    print(f"解析JSON失败: {str(je)}, 原始数据: {received_str}")
                    # 存储原始字符串以便后续处理
                    self.received_data.append(received_str)

            except socket.timeout:
                # 超时但连接仍在，继续等待
                print(f"接收超时 ({self.receive_timeout}秒)，继续等待...")
                continue
            except Exception as e:
                if self.running:
                    print(f"接收数据时发生错误: {str(e)}")
                self.connected = False
                break
        print("接收数据循环已退出")

    def send_data(self, method, parameter=None):
        """
        发送数据命令

        参数:
            method (str): 命令方法名称，如 'init', 'startLeScan' 等
            parameter (dict, optional): 命令参数，默认为 None

        返回:
            bool: 如果发送成功则返回True
        """
        try:
            if not self.connected or not self.socket:
                print("未连接到设备，无法发送数据")
                return False

            # 构建命令字典
            cmd_dict = {"method": method}
            if parameter:
                cmd_dict["parameter"] = parameter
            else:
                cmd_dict["parameter"] = {}

            # 转换为JSON字符串并构建最终发送格式
            cmd_str = json.dumps(cmd_dict)
            send_data = {"PC_CMD": cmd_str}
            send_str = json.dumps(send_data).replace(" ", "") + "\n"

            # 发送数据
            self.socket.sendall(send_str.encode('utf-8'))
            print(f"[TCP/IP_write]: {send_str}")
            return True
        except Exception as e:
            print(f"发送数据失败: {str(e)}")
            return False

    def check_connection(self):
        """
        检查连接状态

        返回:
            bool: 如果连接正常则返回True
        """
        if not self.connected or not self.socket:
            return False

        # 尝试发送一个心跳包或空数据来检查连接
        try:
            self.socket.sendall(b'')
            return True
        except Exception as e:
            print(f"连接检查失败: {str(e)}")
            self.connected = False
            return False

    def read_received_data(self, response_type=None, timeout=None):
        """
        读取接收到的数据，可以设置超时等待

        参数:
            response_type (str, optional): 响应类型，如 'Init_RESPONSE', 'BLE_SCAN' 等，默认为 None
                                           如果指定，则只返回该类型的响应
            timeout (int, optional): 超时等待时间（秒），默认为 None
                                     如果指定，则等待直到超时或收到数据

        返回:
            list: 接收到的所有数据或指定类型的响应
        """
        start_time = time.time()

        # 如果设置了超时，则等待直到超时或收到指定类型的数据
        if timeout:
            while time.time() - start_time < timeout:
                # 检查是否有指定类型的数据
                if response_type:
                    filtered_data = self._filter_data_by_type(response_type)
                    if filtered_data:
                        return filtered_data
                # 如果没有指定类型，检查是否有任何数据
                elif self.received_data:
                    return self.received_data
                time.sleep(0.1)  # 短暂休眠以减少CPU使用率

        # 没有设置超时或已超时，返回当前数据
        if response_type:
            return self._filter_data_by_type(response_type)
        else:
            return self.received_data

    def _filter_data_by_type(self, response_type):
        """
        根据响应类型筛选数据

        参数:
            response_type (str): 响应类型

        返回:
            list: 筛选后的数据(解析后的JSON对象)
        """
        filtered_data = []
        for data in self.received_data:
            try:
                # 检查data是否已经是字典类型
                if isinstance(data, dict):
                    json_data = data
                else:
                    json_data = json.loads(data)
                if response_type in json_data:
                    filtered_data.append(json_data)
            except (json.JSONDecodeError, TypeError):
                continue
        return filtered_data
    
    def start_server(self):
        """
        启动TCP服务器监听连接
    
        返回:
            bool: 如果启动成功则返回True
        """
        try:
            print(f"正在启动TCP服务器，监听端口 {self.port}...")
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind(('0.0.0.0', self.port))
            self.server_socket.listen(1)
            self.running = True
            self.server_thread = threading.Thread(target=self._accept_connections, daemon=True)
            self.server_thread.start()
            print(f"TCP服务器已启动，监听端口 {self.port}")
            return True
        except Exception as e:
            print(f"启动TCP服务器失败: {str(e)}")
            return False
    
    def _accept_connections(self):
        """
        接受客户端连接的内部方法
        """
        while self.running:
            try:
                client_socket, address = self.server_socket.accept()
                print(f"接受到来自 {address} 的连接")
                self.socket = client_socket
                self.connected = True
                # 启动接收线程
                threading.Thread(target=self._receive_data, daemon=True).start()
            except Exception as e:
                if self.running:
                    print(f"接受连接时发生错误: {str(e)}")
                break
    
    def clear_received_data(self):
        """
        清除接收到的数据
    
        返回:
            bool: 如果清除成功则返回True
        """
        self.received_data = []
        return True
    
    def disconnect(self):
        """
        断开连接
    
        返回:
            bool: 如果断开成功则返回True
        """
        try:
            self.running = False
            if self.socket:
                self.socket.close()
                self.socket = None
            if self.server_socket:
                self.server_socket.close()
                self.server_socket = None
            self.connected = False
            print("已断开连接")
            return True
        except Exception as e:
            print(f"断开连接时发生错误: {str(e)}")
            return False

if __name__ == "__main__":
    # 初始化连接
    controller = TCPIPCommunicator(device_ip="10.1.20.159", port=8990)

    # 发送初始化命令
    init_param = {
        "packagesMaxLen": "20",
        "bleface": "WeiXin",
        "maxDistance": "20.0",
        "fill": "false"
    }
    controller.send_data("init", init_param)
    responses = controller.read_received_data("Init_RESPONSE", timeout=5)
    if responses:
        controller.clear_received_data()
    else:
        print("未收到初始化响应")
    
    # 发送扫描命令
    if controller.check_connection():
        scan_param = {
            "WRITE_UUID": "0000FEC7-0000-1000-8000-00805f9b34fb",
            "name": "GV|GD|ETC|GW|SX",
            "READ_UUID": "0000FEC8-0000-1000-8000-00805f9b34fb",
            "SERVICE_UUID": "0000FEE7-0000-1000-8000-00805f9b34fb"
        }
        controller.send_data("startLeScan", scan_param)
        responses = controller.read_received_data("BLE_SCAN", timeout=10)
    else:
        print("连接已断开，无法发送扫描命令")
    if responses:
        controller.clear_received_data()
    else:
        print("未收到扫描响应")

    # 停止扫描
    stop_param = {
    }
    controller.send_data("stopLeScan", stop_param)
    # 修改响应类型为CMD_RESPONSE
    responses = controller.read_received_data("CMD_RESPONSE", timeout=5)
    if responses:
        # 检查是否包含stopLeScan成功响应
        success = any("stopLeScan" in resp.get("CMD_RESPONSE", {}) and resp["CMD_RESPONSE"]["stopLeScan"] == "OK" for resp in responses)
        if success:
            print("停止扫描成功")
        controller.clear_received_data()
    else:
        print("未收到停止扫描响应")
    
    # 连接蓝牙设备
    connect_param = {
        "mac": controller.mac,
    }
    controller.send_data("connect", connect_param)
    # 增加对BLE_STATE响应的处理
    responses = controller.read_received_data("BLE_STATE", timeout=20)
    if responses:
        print("蓝牙连接状态响应已收到")
        controller.clear_received_data()
    else:
        print("未收到蓝牙连接状态响应")

    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("BLE数据读取成功")
        controller.clear_received_data()
    else:
        print("未收到BLE读取响应")

    # 写信息
    write_param = {
        "data": "FE0100124E2100890A06080012024F4B1200",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")
    
    # 写信息
    write_param = {
        "data": "FE0100164E23008A0A06080012024F4B100018002000",
        "isRecvWriteStatus": "true",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    # 写信息
    write_param = {
        "data": "FE0100147531008B0A00120633018001A2221800",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    
    # 写信息
    write_param = {
        "data": "FE0100227531008C0A0012143302800FAC000B008009010700A40000023F003C1800",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    
    # 写信息
    write_param = {
        "data": "FE0100207531008D0A0012123303800DAC000900800701050084000008241800",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    # 写信息
    write_param = {
        "data": "FE0100257531008E0A00121733048012AC000E00800C010A04D6811A050147EAD353D31800",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    # 写信息
    write_param = {
        "data": "FE0100207531008F0A0012123305800DAC0009008007010500B0811A01841800",
    }
    controller.send_data("write", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_READ", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")

    # 写信息
    write_param = {
    }
    controller.send_data("disconnect", write_param)
    # 等待BLE_READ响应
    responses = controller.read_received_data("BLE_STATE", timeout=5)
    if responses:
        print("写信息成功")
        controller.clear_received_data()
    else:
        print("未收到写信息响应")
